package com.hf.hantopy.utils.excel;

import com.hf.hantopy.utils.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Date: 2019/3/21
 * @Auther: wm yu
 */
public class CommonUtil {


    /**
     * 获取含有ExcelField注解的所有字段名
     * @param sheetClass
     */
    public static void getAnnoFields(Class<?> sheetClass, List<String> headList){
        if(null != sheetClass){
            Field[] fields = sheetClass.getDeclaredFields();
            Arrays.stream(fields).filter((Field field) -> field.isAnnotationPresent(ExcelField.class)).forEach(var -> {
                headList.add(var.getName());
            });
        }
    }

    /**
     * 获取指定类的所有字段
     * @param sheetClass
     * @return
     */
    public static Field[] getAllFields(Class<?> sheetClass) {
        if(null != sheetClass){
            Field[] fields = sheetClass.getDeclaredFields();
            //排除掉static和final
            List<Field> list = Arrays.stream(fields).filter((Field field) -> (!Modifier.isStatic(field.getModifiers())) && !Modifier.isFinal(field.getModifiers())).collect(Collectors.toList());
            fields = new  Field[list.size()];
            list.toArray(fields);
            return fields;
        }
        return null;
    }


    public static Byte parseByte(String value) {
        try {
            value = value.replaceAll("　", "");
            return Byte.valueOf(value);
        } catch(NumberFormatException e) {
            throw new RuntimeException("parseByte but input illegal input=" + value, e);
        }
    }

    public static Boolean parseBoolean(String value) {
        value = value.replaceAll("　", "");
        if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
            return Boolean.TRUE;
        } else if (Boolean.FALSE.toString().equalsIgnoreCase(value)) {
            return Boolean.FALSE;
        } else {
            throw new RuntimeException("parseBoolean but input illegal input=" + value);
        }
    }

    public static Integer parseInt(String value) {
        try {
            value = value.replaceAll("　", "");
            return Integer.valueOf(value);
        } catch(NumberFormatException e) {
            throw new RuntimeException("parseInt but input illegal input=" + value, e);
        }
    }

    public static Short parseShort(String value) {
        try {
            value = value.replaceAll("　", "");
            return Short.valueOf(value);
        } catch(NumberFormatException e) {
            throw new RuntimeException("parseShort but input illegal input=" + value, e);
        }
    }

    public static Long parseLong(String value) {
        try {
            value = value.replaceAll("　", "");
            return Long.valueOf(value);
        } catch(NumberFormatException e) {
            throw new RuntimeException("parseLong but input illegal input=" + value, e);
        }
    }

    public static Float parseFloat(String value) {
        try {
            value = value.replaceAll("　", "");
            return Float.valueOf(value);
        } catch(NumberFormatException e) {
            throw new RuntimeException("parseFloat but input illegal input=" + value, e);
        }
    }

    public static Double parseDouble(String value) {
        try {
            value = value.replaceAll("　", "");
            return Double.valueOf(value);
        } catch(NumberFormatException e) {
            throw new RuntimeException("parseDouble but input illegal input=" + value, e);
        }
    }

    public static Date parseDate(String value, ExcelFormat excelFormat) {
        try {
            String datePattern = "yyyy-MM-dd HH:mm:ss";
            if (excelFormat != null) {
                datePattern = excelFormat.pattern();
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
            return dateFormat.parse(value);
        } catch(ParseException e) {
            throw new RuntimeException("parseDate but input illegal input=" + value, e);
        }
    }

    /**
     * 参数解析 （支持：Byte、Boolean、String、Short、Integer、Long、Float、Double、Date）
     *
     * @param field
     * @param value
     * @return Object
     */
    public static Object parseValue(Field field, String value) {
        Class<?> fieldType = field.getType();

        ExcelFormat excelFormat = field.getAnnotation(ExcelFormat.class);
        if(value==null || value.trim().length()==0){
            return null;
        }
        value = value.trim();

        if (Boolean.class.equals(fieldType) || Boolean.TYPE.equals(fieldType)) {
            return parseBoolean(value);
        }else if (String.class.equals(fieldType)) {
            return value;
        } else if (Short.class.equals(fieldType) || Short.TYPE.equals(fieldType)) {
            return parseShort(value);
        } else if (Integer.class.equals(fieldType) || Integer.TYPE.equals(fieldType)) {
            return parseInt(value);
        } else if (Long.class.equals(fieldType) || Long.TYPE.equals(fieldType)) {
            return parseLong(value);
        } else if (Float.class.equals(fieldType) || Float.TYPE.equals(fieldType)) {
            return parseFloat(value);
        } else if (Double.class.equals(fieldType) || Double.TYPE.equals(fieldType)) {
            return parseDouble(value);
        } else if (Date.class.equals(fieldType)) {
            return parseDate(value, excelFormat);

        } else {
            throw new RuntimeException("request illeagal type, type must be Integer not int Long not long etc, type=" + fieldType);
        }
    }

    /**
     * 参数格式化为String
     *
     * @param field
     * @param value
     * @return String
     */
    public static String formatValue(Field field, Object value) {
        Class<?> fieldType = field.getType();
        if(value==null) {
            return "";
        }
        if(field.isAnnotationPresent(ExcelCodeToString.class)){
            String [] codeStrings=field.getAnnotation(ExcelCodeToString.class).values();
            for(String str : codeStrings) {
                String[] split = str.split(":");
                String code =split[0];
                String string =split[1];

                if(code.equals(String.valueOf(value))) {
                    return string;
                }else {
                }
            }
            return "undefined";
        }else if (Boolean.class.equals(fieldType) || Boolean.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (String.class.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Short.class.equals(fieldType) || Short.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Integer.class.equals(fieldType) || Integer.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Long.class.equals(fieldType) || Long.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Float.class.equals(fieldType) || Float.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Double.class.equals(fieldType) || Double.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Date.class.equals(fieldType)) {
            String datePattern = "yyyy-MM-dd HH:mm:ss";
            if(field.isAnnotationPresent(ExcelFormat.class)){
                datePattern=field.getAnnotation(ExcelFormat.class).pattern();
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
            return dateFormat.format(value);
        } else {
            throw new RuntimeException("request illeagal type, type must be Integer not int Long not long etc, type=" + fieldType);
        }
    }


    /**
     * 将Excel中的数据转换为对象,根据@ExcelField注解上的值来确定
     */
    public static List<Object> ExcelData2Object(List<Map<String,Object>> dataList,Class<?> clzz){
        List<Map<String, Object>> resultList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(dataList)){
            dataList.stream().forEach(map -> {
                Field[] fields = clzz.getDeclaredFields();
                Map<String, Object> tempMap = new HashMap<>();
                if(!CollectionUtils.isEmpty(Arrays.asList(fields))){
                    Arrays.stream(fields).filter((Field f) -> f.isAnnotationPresent(ExcelField.class)).forEach(field -> {
                        String name = field.getAnnotation(ExcelField.class).name();
                        //获取map的key,也就是对应@ExcelField注解上面的值
                        map.entrySet().stream().forEach(mmp -> {
                            if(mmp.getKey().equals(name)){
                                //判断该属性上是否有@ExcelCodeToString注解,如果有需要做转换
                               if(field.isAnnotationPresent(ExcelCodeToString.class)){
                                   String[] values = field.getAnnotation(ExcelCodeToString.class).values();
                                   Arrays.stream(values).forEach(var -> {
                                       if(map.get(mmp.getKey()).equals(var.split(":")[1])){
                                           int status = Integer.parseInt(var.split(":")[0]);
                                           tempMap.put(field.getName(),status);
                                           return;
                                       }
                                   });
                               }else{
                                 tempMap.put(field.getName(),map.get(mmp.getKey()));
                               }
                            }
                        });
                    });
                }
                resultList.add(tempMap);
            });
        }
        //处理状态值转换




        List<Object> objectList = new ArrayList<>();
        //将map转换为对象
        resultList.stream().forEach(var -> {
            Object o = BeanUtils.map2Object(var, clzz);
            objectList.add(o);
        });
        return objectList;
    }
}
